package sdk

import (
	"context"
	"encoding/json"
	"fmt"
	"net/url"

	"github.com/yourusername/virt-manager-go/internal/models"
)

// DomainClient 提供虚拟机管理相关的 API 操作
type DomainClient struct {
	client *APIClient
}

// NewDomainClient 创建新的虚拟机客户端
func NewDomainClient(client *APIClient) *DomainClient {
	return &DomainClient{
		client: client,
	}
}

// ListDomains 列出指定连接的所有虚拟机
func (d *DomainClient) ListDomains(ctx context.Context, connectionID string) ([]models.DomainSummary, error) {
	// 构建带查询参数的URL
	u := "/api/v1/domains"
	if connectionID != "" {
		u = fmt.Sprintf("/api/v1/domains?connection=%s", url.QueryEscape(connectionID))
	}

	data, err := d.client.Get(ctx, u)
	if err != nil {
		return nil, fmt.Errorf("failed to list domains for connection %s: %w", connectionID, err)
	}

	// API 返回的是包装格式 {"domains": [...], "count": n}
	var response struct {
		Domains []models.DomainSummary `json:"domains"`
		Count   int                    `json:"count"`
	}
	if err := json.Unmarshal(data, &response); err != nil {
		return nil, fmt.Errorf("failed to unmarshal domains response: %w", err)
	}

	return response.Domains, nil
}

// GetDomain 获取指定连接的虚拟机详情
func (d *DomainClient) GetDomain(ctx context.Context, connectionID, name string) (*models.DomainDetail, error) {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/domain?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(name))

	data, err := d.client.Get(ctx, u)
	if err != nil {
		return nil, fmt.Errorf("failed to get domain for connection %s: %w", connectionID, err)
	}

	var domain models.DomainDetail
	if err := json.Unmarshal(data, &domain); err != nil {
		return nil, fmt.Errorf("failed to unmarshal domain: %w", err)
	}

	return &domain, nil
}

// CreateDomain 在指定连接创建新虚拟机
func (d *DomainClient) CreateDomain(ctx context.Context, connectionID string, req *models.CreateDomainRequest) error {
	// 构建带查询参数的URL
	u := "/api/v1/domains"
	if connectionID != "" {
		u = fmt.Sprintf("/api/v1/domains?connection=%s", url.QueryEscape(connectionID))
	}

	_, err := d.client.Post(ctx, u, req)
	if err != nil {
		return fmt.Errorf("failed to create domain for connection %s: %w", connectionID, err)
	}
	return nil
}

// DeleteDomain 删除指定连接的虚拟机
func (d *DomainClient) DeleteDomain(ctx context.Context, connectionID, name string) error {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/domain?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(name))

	_, err := d.client.Delete(ctx, u)
	if err != nil {
		return fmt.Errorf("failed to delete domain for connection %s: %w", connectionID, err)
	}
	return nil
}

// StartDomain 启动指定连接的虚拟机
func (d *DomainClient) StartDomain(ctx context.Context, connectionID, name string) error {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/domain/start?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(name))

	_, err := d.client.Post(ctx, u, nil)
	if err != nil {
		return fmt.Errorf("failed to start domain for connection %s: %w", connectionID, err)
	}
	return nil
}

// ShutdownDomain 关闭指定连接的虚拟机
func (d *DomainClient) ShutdownDomain(ctx context.Context, connectionID, name string) error {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/domain/shutdown?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(name))

	_, err := d.client.Post(ctx, u, nil)
	if err != nil {
		return fmt.Errorf("failed to shutdown domain for connection %s: %w", connectionID, err)
	}
	return nil
}

// RebootDomain 重启指定连接的虚拟机
func (d *DomainClient) RebootDomain(ctx context.Context, connectionID, name string) error {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/domain/reboot?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(name))

	_, err := d.client.Post(ctx, u, nil)
	if err != nil {
		return fmt.Errorf("failed to reboot domain for connection %s: %w", connectionID, err)
	}
	return nil
}

// ForceStopDomain 强制停止指定连接的虚拟机
func (d *DomainClient) ForceStopDomain(ctx context.Context, connectionID, name string) error {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/domain/force-stop?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(name))

	_, err := d.client.Post(ctx, u, nil)
	if err != nil {
		return fmt.Errorf("failed to force stop domain for connection %s: %w", connectionID, err)
	}
	return nil
}

// SuspendDomain 暂停指定连接的虚拟机
func (d *DomainClient) SuspendDomain(ctx context.Context, connectionID, name string) error {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/domain/suspend?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(name))

	_, err := d.client.Post(ctx, u, nil)
	if err != nil {
		return fmt.Errorf("failed to suspend domain for connection %s: %w", connectionID, err)
	}
	return nil
}

// ResumeDomain 恢复指定连接的虚拟机
func (d *DomainClient) ResumeDomain(ctx context.Context, connectionID, name string) error {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/domain/resume?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(name))

	_, err := d.client.Post(ctx, u, nil)
	if err != nil {
		return fmt.Errorf("failed to resume domain for connection %s: %w", connectionID, err)
	}
	return nil
}

// SetVCPUs 设置指定连接虚拟机的 vCPU 数量
func (d *DomainClient) SetVCPUs(ctx context.Context, connectionID, name string, vcpus uint) error {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/domain/vcpus?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(name))

	req := map[string]interface{}{
		"vcpus": vcpus,
	}

	_, err := d.client.Put(ctx, u, req)
	if err != nil {
		return fmt.Errorf("failed to set vcpus for connection %s: %w", connectionID, err)
	}
	return nil
}

// SetMemory 设置指定连接虚拟机的内存
func (d *DomainClient) SetMemory(ctx context.Context, connectionID, name string, memory uint64) error {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/domain/memory?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(name))

	req := map[string]interface{}{
		"memory": memory,
	}

	_, err := d.client.Put(ctx, u, req)
	if err != nil {
		return fmt.Errorf("failed to set memory for connection %s: %w", connectionID, err)
	}
	return nil
}

// GetDomainXML 获取指定连接虚拟机的 XML 配置
func (d *DomainClient) GetDomainXML(ctx context.Context, connectionID, name string) (string, error) {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/domain/xml?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(name))

	data, err := d.client.Get(ctx, u)
	if err != nil {
		return "", fmt.Errorf("failed to get domain xml for connection %s: %w", connectionID, err)
	}

	return string(data), nil
}

// GetDomainStats 获取指定连接虚拟机的统计信息
func (d *DomainClient) GetDomainStats(ctx context.Context, connectionID, name string) (map[string]interface{}, error) {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/domain/stats?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(name))

	data, err := d.client.Get(ctx, u)
	if err != nil {
		return nil, fmt.Errorf("failed to get domain stats for connection %s: %w", connectionID, err)
	}

	var stats map[string]interface{}
	if err := json.Unmarshal(data, &stats); err != nil {
		return nil, fmt.Errorf("failed to unmarshal stats: %w", err)
	}

	return stats, nil
}

// GetDomainStatus 获取指定连接虚拟机的状态
func (d *DomainClient) GetDomainStatus(ctx context.Context, connectionID, name string) (map[string]interface{}, error) {
	// 构建带查询参数的URL
	u := fmt.Sprintf("/api/v1/domain/status?connection=%s&name=%s", url.QueryEscape(connectionID), url.QueryEscape(name))

	data, err := d.client.Get(ctx, u)
	if err != nil {
		return nil, fmt.Errorf("failed to get domain status for connection %s: %w", connectionID, err)
	}

	var status map[string]interface{}
	if err := json.Unmarshal(data, &status); err != nil {
		return nil, fmt.Errorf("failed to unmarshal status: %w", err)
	}

	return status, nil
}

// GenerateFromTemplate 从模板生成域XML
func (d *DomainClient) GenerateFromTemplate(ctx context.Context, req *models.CreateDomainRequest) (string, error) {
	data, err := d.client.Post(ctx, "/api/v1/templates/generate", req)
	if err != nil {
		return "", fmt.Errorf("failed to generate domain from template: %w", err)
	}

	return string(data), nil
}
